/*
 * HighBoost.cpp
 *
 *  Created on: Dec 6, 2009
 */

#include "HighBoost.h"

HighBoost::HighBoost(double value) {
	setValue(value);
}

HighBoost::HighBoost() {
}

HighBoost::~HighBoost() {
}

ImageEntity *HighBoost::apply(ImageEntity *originalImageEntity) {
	ImageEntity *image = getLowPass().apply(originalImageEntity);

	int width = image->getWidth();
	int height = image->getHeight();
	int fileSize = image->getFileSize();

	int **newVectorsR = NULL;
	if (originalImageEntity->getVectorsR() != NULL && image->getVectorsR() != NULL) {
		newVectorsR = new int*[height];
		for (int i = 0; i < width; i++) {
			newVectorsR[i] = new int[width];
		}

		applyFilterInVector(width, height, originalImageEntity->getVectorsR(), image->getVectorsR(), newVectorsR);
	}



	int **newVectorsG = NULL;
	if (originalImageEntity->getVectorsG() != NULL && image->getVectorsG() != NULL) {
		newVectorsG = new int*[height];
		for (int i = 0; i < width; i++) {
			newVectorsG[i] = new int[width];
		}

		applyFilterInVector(width, height, originalImageEntity->getVectorsG(), image->getVectorsG(), newVectorsG);
	}

	int **newVectorsB = NULL;
	if (originalImageEntity->getVectorsB() != NULL && image->getVectorsB() != NULL) {
		newVectorsB = new int*[height];
		for (int i = 0; i < width; i++) {
			newVectorsB[i] = new int[width];
		}

		applyFilterInVector(width, height, originalImageEntity->getVectorsB(), image->getVectorsB(), newVectorsB);
	}

	delete image;
	return new ImageEntity(width, height, fileSize, newVectorsR, newVectorsG, newVectorsB);
}

void HighBoost::applyFilterInVector(int width, int height, int **vectors, int **lowVectors, int **newVectors) const {
	#pragma omp parallel for default(shared)
	for (int i = 0; i < height; i++) {
		#pragma omp parallel for default(shared)
		for (int j = 0; j < width; j++) {

			int value = (int) round(vectors[i][j] * getValue() - lowVectors[i][j]);

			if (value > 256) {
				value = 256;
			}

			if (value < 0) {
				value = 0;
			}

			newVectors[i][j] = value;
		}
	}
}

//	GETs AND SETs
void HighBoost::setValue(double value) {
	this->value = value;
}

double HighBoost::getValue() const {
	return value;
}

void HighBoost::setLowPass(LowPass lowPass) {
	this->lowPass = lowPass;
}

LowPass HighBoost::getLowPass() const {
	return lowPass;
}
